<!DOCTYPE html>
<html>
<head>
	<meta charset="utf-8">
	<meta http-equiv="X-UA-Compatible" content="IE=edge">
	<title>面向对象</title>
</head>
<body>
	<script>
		//类的声明

	function Animal1(){
			this.name=name;
		}

		//es6声明类
		class Animal2{
			constructor(){
				this.name=name;
			}
		}

		//实例化一个对象
		//构造函数没有参数的化，实例的对象括号里边也不需要参数
		console.log(new Animal1(),new Animal2())

		//继承方式
		
		//借助构造函数实现继承(部分继承)
		//缺点：Parent1原型链上的东西，并没有被Child1所继承。
		function Parent1(){
			this.name="parent1";
		}
		Parent1.prototype.say=function(){
			console.log("hello")
		}
		function Child1(){
			Parent1.call(this);//apply
			//将父级的构造函数的this指向子类的构造函数的实例上。
			this.type="child1";
		}
		console.log(new Child1)

		//借助于原型链实现继承
		//缺点：共用同样的原型对象，其中一个实例对原型对象修改，就会造成对全部实例的原型对象修改。
		function Parent2(){
			this.name="parent2";
			this.play=[1,2,3];
		}

		function Child2(){
			this.type="child2"
		}

		Child2.prototype=new Parent2();//实现继承
		console.log(new Child2())
		console.log(new Child2().__proto__===Child2.prototype)//true

		var s1=new Child2();
		var s2=new Child2();

		console.log(s1.play,s2.play)

		s1.play.push(4);
		console.log(s1.play,s2.play);
		// 原因：引用的是同样的原型链对象
		s1.__proto__===s2.__proto__;

		//组合方式
		//缺点：父级的构造函数执行了两次。
		function Parent3(){
			this.name="parent3";
			this.play=[1,2,3,4];
		}
		function Child3(){
			Parent3.call(this);
			this.type="child3"
		}
		Child3.prototype=new Parent3();
		var s3 = new Child3();
		var s4 = new Child3();
		s3.play.push(5);
		console.log(s3.play,s4.play)

		//组合继承的优化1
		//缺点：指向了同一个构造函数
		function Parent4(){
			this.name="parent4";
			this.play=[1,2,3,4];
		}
		function Child4(){
			Parent4.call(this);
			this.type="child3"
		}
		Child4.prototype=Parent4.prototype;
		var s5 = new Child4();
		var s6 = new Child4();
		s5.play.push(5);
		console.log(s5,s6)


		//!!!!!!!!组合继承的优化2
		function Parent5(){
			this.name="parent4";
			this.play=[1,2,3,4];
		}
		function Child5(){
			Parent5.call(this);
			this.type="child3"
		}
		Child5.prototype=Object.create(Parent5.prototype);
		//通过创建中间对象的方法，它的原型对象就是父类的原型对象
		//对象之间是通过__prot__寻找其原型对象
		Child5.prototype.constructor=Child5;
		var s7 = new Child5();
		var s8 = new Child5();
		s7.play.push(5);
		console.log(s7,s8);
	</script>
</body>
</html>